package com.jeesite.modules.app.util.wx;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.CharsetUtil;

public class NioWebSocketHandler extends SimpleChannelInboundHandler<Object>{
     private final Logger logger=LoggerFactory.getLogger(this.getClass());
     public static final String HEART_BEAT = "heart";
     private WebSocketServerHandshaker handshaker;
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
		logger.debug("收到消息:"+msg);
		if(msg instanceof FullHttpRequest){
			handleHttpRequest(ctx,(FullHttpRequest)msg);
		}else if(msg instanceof WebSocketFrame){
			handlerWebSocketFram(ctx,(WebSocketFrame)msg);
		}
		
	}
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		logger.debug("客户端加入链接:"+ctx.channel());
		 ChannelSupervise.addChannel(ctx.channel());
	}
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		logger.debug("客户端断开连接"+ctx.channel());
	    ChannelSupervise.removeChannel(ctx.channel());
	}
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}
	private static Map<String, String> map=new HashMap<String, String>();
	private void handlerWebSocketFram(ChannelHandlerContext ctx,WebSocketFrame frame){
		if(frame instanceof CloseWebSocketFrame){
			handshaker.close(ctx.channel(),(CloseWebSocketFrame)frame.retain());
			return;
		}
		if(frame instanceof PingWebSocketFrame){
			ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
			return;
		}
		if(!(frame instanceof TextWebSocketFrame)){
			logger.debug("本例程仅支持文本消息，不支持二进制消息");
            throw new UnsupportedOperationException(String.format(
                    "%s frame types not supported", frame.getClass().getName()));
		}
		//返回应答消息
		String request=((TextWebSocketFrame)frame).text();
		logger.debug("服务端收到："+request);
		JSONObject parseObject = JSONObject.parseObject(request);
		if(parseObject.containsKey("userId")){
			String userId=parseObject.getString("userId");
			map.put(userId, ctx.channel().id().asShortText());
		}
//		TextWebSocketFrame tws=new TextWebSocketFrame(new Date().toString()+ctx.channel().id()+":"+request);
		//群发
//		ChannelSupervise.send2All(tws);
		//返回谁发的发给谁
//		ctx.channel().writeAndFlush(tws);
	}
	private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
		if(!req.decoderResult().isSuccess()||(!"websocket".equals(req.headers().get("Upgrade")))){
			sendHttpResponse(ctx,req,new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
			return;
		}
		WebSocketServerHandshakerFactory wsFactory=new WebSocketServerHandshakerFactory("wx://localhost:8888/websocket", null, false);
		handshaker=wsFactory.newHandshaker(req);
		if(handshaker==null){
			WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
		}else{
			handshaker.handshake(ctx.channel(), req);
		}
		
	}
   public static void sendMessage(String message){
		  if(StringUtils.isNotBlank(message)){
			  TextWebSocketFrame tws=new TextWebSocketFrame(message);
			  ChannelSupervise.send2All(tws);
		  }
	   
   }
	private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req,
			DefaultFullHttpResponse res) {
		 if(res.status().code()!=200){
			 ByteBuf buf=Unpooled.copiedBuffer(res.status().toString(),CharsetUtil.UTF_8);
			 res.content().writeBytes(buf);
			 buf.release();
		 }
		 ChannelFuture f=ctx.channel().writeAndFlush(res);
		 //如果是非keep-Alive,关闭连接 isKeepAlive(req)
		 if(res.status().code()!=200){
			 f.addListener(ChannelFutureListener.CLOSE);
		 }
		
	}
}
